package com.huixi.weiju.service.userModel;

import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson.JSON;
import com.huixi.weiju.dao.userModel.UserDao;
import com.huixi.weiju.dao.userModel.UserWxDao;
import com.huixi.weiju.exception.enums.ResultCode;
import com.huixi.weiju.exception.enums.UserCode;
import com.huixi.weiju.pojo.userModel.DO.UserDO;
import com.huixi.weiju.pojo.userModel.DO.UserWxDO;
import com.huixi.weiju.pojo.userModel.DTO.WxDecodeUserInfoDTO;
import com.huixi.weiju.pojo.userModel.DTO.WxSesssionKeyDTO;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.util.Arrays;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 用户模块的，进行大量逻辑处理工作
 *
 * @author: 李辉
 * @date: 2019/11/21 1:42
 * @param:
 * @return:
 */
@Service
@Slf4j
public class UserService {


    @Value("${weiJu.appId}")
    private String appId;

    @Value("${weiJu.appSecret}")
    private String appSecret;


    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    UserDao userDao;

    @Autowired
    UserWxDao userWxDao;

    /**
     *  获取session_key
     * @Author 李辉
     * @Date 2019/11/23 4:31
     * @param code 用户code
     * @return java.lang.String
     **/
    public String getWxSessionKey(String code) throws IOException {

        String sessionKeyToUuid = UUID.randomUUID().toString();


        URL url = new URL("https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + appSecret + "&js_code" +
                "=" + code + "&grant_type=authorization_code");

        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

        BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
        String line = null;
        StringBuilder result = new StringBuilder();
        while ((line = br.readLine()) != null) {
            result.append(line);
        }
        connection.disconnect();


        WxSesssionKeyDTO wxSesssionKeyDTO = JSON.parseObject(result.toString(), WxSesssionKeyDTO.class);

        // 放到redis 中存储一个小时 (session_key 本生的有效期就没有多长,估计就两个小时)
        try {
            redisTemplate.opsForValue().set(sessionKeyToUuid, wxSesssionKeyDTO, 1, TimeUnit.HOURS);
        } catch (Exception e) {
            log.error(ResultCode.REDIS001.getMessage() + "|" + e.getMessage());
        }


        return sessionKeyToUuid;

    }


    /**
     *  获取用户加密信息 并且保存
     * @Author 李辉 
     * @Date 2019/11/23 4:33
     * @param
     * @return void
     **/
    public UserDO getEncryptionUserInfo(String encryptedData, String session_key, String ivKey) {
        byte[] encode = Base64.decode(encryptedData);
        byte[] aeskey = Base64.decode(session_key);
        byte[] iv = Base64.decode(ivKey);

        String result = null;

        try {
            // 如果密钥不足16位，那么就补足.  这个if 中的内容很重要
            int base = 16;
            if (aeskey.length % base != 0) {
                int groups = aeskey.length / base + (aeskey.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(aeskey, 0, temp, 0, aeskey.length);
                aeskey = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
            SecretKeySpec spec = new SecretKeySpec(aeskey, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(iv));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(encode);
            if (null != resultByte && resultByte.length > 0) {
                result = new String(resultByte, "UTF-8");
                System.out.println(result);
            }
        } catch (Exception e) {
            log.error(UserCode.USER004.getMessage() +"|"+ e.getMessage());
        }

        WxDecodeUserInfoDTO wxDecodeUserInfoDTO = JSON.parseObject(result, WxDecodeUserInfoDTO.class);

        // 统一的UUID
        String uuid = UUID.randomUUID().toString().replaceAll("-","");

        // 统一的创建时间
        Date createDate = new Date();


        // 存到用户 表
        UserDO userDO = new UserDO();
        userDO.setUserId(uuid); // 用户id
        userDO.setNickName(wxDecodeUserInfoDTO.getNickName()); // 用户名称
        userDO.setHeadPortrait(wxDecodeUserInfoDTO.getAvatarUrl()); // 头像URL地址
        userDO.setSex(wxDecodeUserInfoDTO.getGender()); // 性别
        userDO.setSignature("快乐源于分享");
        userDO.setIntroduce("欢迎各位 start");
        userDO.setCreateBy(uuid); // 创建人
        userDO.setCreateDate(createDate); // 创建时间

        int i = userDao.insertCondition(userDO);


        // 存到用户相关的微信信息 表
        UserWxDO userWxDO = new UserWxDO();
        userWxDO.setUserId(uuid);
        userWxDO.setWxOpenId(wxDecodeUserInfoDTO.getOpenId());
        userWxDO.setWxUnionId(wxDecodeUserInfoDTO.getUnionId());
        userWxDO.setWxAppId(wxDecodeUserInfoDTO.getWatermark().getAppid());

        int i1 = userWxDao.insertCondition(userWxDO);

        return userDO;


    }


    /**
     *  检测用户登录情况 授权过就直接返还信息给他 | 反之就给null
     * @Author 李辉 
     * @Date 2019/11/24 21:10
     * @param code 用户code
     * @return com.huixi.weiju.pojo.userModel.DO.UserDO
     **/
    public UserDO detectionUserAuthorization(String code) throws Exception {

        URL url = new URL("https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + appSecret + "&js_code" +
                "=" + code + "&grant_type=authorization_code");

        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

        BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
        String line = null;
        StringBuilder result = new StringBuilder();
        while ((line = br.readLine()) != null) {
            result.append(line);
        }
        connection.disconnect();


        WxSesssionKeyDTO wxSesssionKeyDTO = JSON.parseObject(result.toString(), WxSesssionKeyDTO.class);

        // 检查数据库中是否有数据
        UserWxDO userWxDO = userWxDao.selectByPrimaryOpenId(wxSesssionKeyDTO.getOpenid());
        if(userWxDO == null) {
            return null;
        }

        // 存在就返回给前端
        UserDO userDO = userDao.selectByPrimaryKey(userWxDO.getUserId());

        return userDO;


    }


}
